package org.brisling.authorize.shiro;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.util.ThreadContext;
import org.apache.shiro.web.subject.WebSubject;
import org.brisling.base.domain.RetDomain;
import org.brisling.base.domain.SimpleResponseObj;
import org.brisling.common.ConstSysParam;
import org.brisling.common.SysConfig;
import org.brisling.common.exception.SessionExpiredException;
import org.brisling.common.exception.UserameOrPasswordWrongException;
import org.brisling.common.util.EncrptUtil;
import org.brisling.common.util.LongUtil;
import org.brisling.sysman.domain.Department;
import org.brisling.sysman.domain.Permissions;
import org.brisling.sysman.domain.UserPassword;
import org.brisling.sysman.domain.Users;
import org.brisling.sysman.queryService.QueryDeptService;
import org.brisling.sysman.queryService.QueryJobRoleService;
import org.brisling.sysman.queryService.QueryPermissionService;
import org.brisling.sysman.queryService.QueryUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

/**
 * 
 * shiro安全服务类
 * @author : jackson wang
 * @Date   : 2015年10月8日 下午10:01:07
 * @version: 1.0
 * 
 */
@RestController
public class ShiroSecurityService {

	
	
	private boolean useSSOLoginCheck ;	
	
	@SuppressWarnings("unused")
	private String superUserIdentify ;
	@Autowired
	private QueryDeptService queryDeptService;
	
	@Autowired
	private QueryJobRoleService queryJobroleService;
	
//	@Autowired
//	private QueryPortalService qryPortalService;
	
	@Autowired
	private QueryUserService queryUserService;
	
	@Autowired
	private QueryPermissionService queryPermissionService;
	
//	@Autowired
//	private PermissionService permissionService;
	
	private String default_site = "risk";
	
	private String mainPage="/main.action";
	
	@PersistenceContext(unitName=ConstSysParam.SUBSYSTEM_SYSMAN)
	private EntityManager entityManager;
	
	
	public ShiroSecurityService(){
		
	}
	
	private static final Log log = LogFactory.getLog(ShiroSecurityService.class);
	
	
	/**
	 * 登录系统
	 * @param username	用户名
	 * @param site		站点
	 * @param session		spring mvc session 对象
	 * @param request		spring mvc request	对象
	 * @param response		spring mvc response 对象
	 * @return
	 * @throws UserameOrPasswordWrongException
	 * @throws SessionExpiredException
	 */
	@RequestMapping("/biz/ssoLogin.action")
	@ResponseBody
	public SimpleResponseObj ssoLogin(@RequestParam(value="userid",required=false) String uid,
						@RequestParam(value="site",required=false) String site,
						HttpSession session,
						HttpServletRequest request,
						HttpServletResponse response) throws UserameOrPasswordWrongException, SessionExpiredException{
		
		SimpleResponseObj so = new SimpleResponseObj();
		if(uid==null){
			log.error( "error.login.generic, session has been expired.  Please relogin again." );
			throw new SessionExpiredException();
		}		
		
		so.setUserid(uid);
		//设定site值
        String _site = (site==null)||(site.trim().length()<=0)?null:site.trim();
            
        String allowSite = SysConfig.getConfig("SSOsite");
        
        if(allowSite==null || allowSite.indexOf(_site)<0){
        	so.setRetStatus("error");
        	so.setRetStr("当前站点不允许该登录模式.");
	        return so;
        }
//        boolean ignoreLogin = true;       

        //单点登录系统		
		UserPassword up= queryUserService.getUserPassword(uid);
		String userid = null;
		if(up!=null && up.getYhid()!=null){
			userid = up.getYhid().trim();			
				PrincipalCollection ssoPrincipal = new SimplePrincipalCollection(
						userid, "ShiroRealm");
				WebSubject.Builder builder = new WebSubject.Builder(request,response);
				builder.principals(ssoPrincipal);
				builder.authenticated(true);
				WebSubject subject = builder.buildWebSubject();
				ThreadContext.bind(subject);			
		}       
			
		Users usr = this.getCurrentUser();
		Department dept = null;
		
		//登录用户信息判断
		if((usr!=null) && (usr.getDeptid()!=null)){
//			Department dept = departmentService.getOne(usr.getDeptid());
			dept = queryDeptService.getOne(usr.getDeptid());
			usr.setDeptid(dept.getId());
			Map<String,String> jobmap = new HashMap<String,String>();
			jobmap.put("userid", usr.getId().toString());
			usr.setJobrole(queryJobroleService.getList(jobmap,false));
			SysConfig.setUsr(usr);
			
			session.setAttribute(ConstSysParam.SYS_USERID, usr.getIdentify());
		}else{       
	        so.setRetStatus("error");
	        so.setRetStr("登录用户不存在");
	        return so;
		}
		
		
        //获取session
		if(session!=null){			
			
			session.setAttribute(ConstSysParam.SITE_SESSION, _site);	
		}
			
        
        
        so.setRetStr(_site + mainPage);
        so.setRetData(usr);
        so.setRetStatus("success");
        return so;

	}
	
	/**
	 * 登录系统
	 * @param username	用户名
	 * @param password	密码
	 * @param site		站点
	 * @param isRememberMe	是否记住用户账号及密码
	 * @param body			参数字符串
	 * @param session		spring mvc session 对象
	 * @param request		spring mvc request	对象
	 * @param response		spring mvc response 对象
	 * @return
	 * @throws UserameOrPasswordWrongException
	 * @throws SessionExpiredException
	 */
	@RequestMapping("/biz/login.action")
	@ResponseBody
	public SimpleResponseObj sysLogin(@RequestParam(value="loginname",required=false) String username,
						@RequestParam(value="password",required=false) String password,
						@RequestParam(value="site",required=false) String site,
						@RequestParam(value="logintype",required=false) String logintype,
						@RequestParam(value="remenberme",required=false) Boolean isRememberMe,						
						@RequestBody(required=false) String body,HttpSession session,
						HttpServletRequest request,
						HttpServletResponse response) throws UserameOrPasswordWrongException, SessionExpiredException{
		
		
		//允许跨域访问
		response.setHeader("Access-Control-Allow-Origin", "*");
		
		SimpleResponseObj so = new SimpleResponseObj();
		if(username==null){
			log.error( "error.login.generic, session has been expired.  Please relogin again." );
			throw new SessionExpiredException();
		}
		
		//so.setUserid(username);
		/**
		 * 单点登录模式
		 */
		if(logintype!=null){
			return ssoLogin(username,site,session,request,response);
		}
		
		if(isRememberMe==null)
			isRememberMe = false;
		
		UsernamePasswordToken token = new UsernamePasswordToken(username, password, isRememberMe);
		
		//免验证登录
		Boolean ssoCheckin = false;
		
		//设定site值
        String _site = null;
        useSSOLoginCheck = SysConfig.getUsingSSO();
        
       
//        boolean ignoreLogin = true;
        
       

        	//单点登录系统
		if(useSSOLoginCheck){
			
			UserPassword up= queryUserService.getUserPassword(username);
			String userid = null;
			if(up!=null && up.getYhid()!=null){
				userid = up.getYhid().trim();
				so.setUserid(userid);
				//判断是否为测试用户
				String _status = null;
				if(SysConfig.isTestUser(username) || 
						(logintype!=null && logintype.trim().compareTo("sso")==1)){
					_status = "success";
				}else{
	//				UserPassword up= queryUserService.getUserPassword(username);
	//				RetDomain rd =SSOService.verifyMD5(username, password,up.getYhmm());
					RetDomain rd =SSOService.verifyPassword(userid, password,up.getYhmm());
					
					if(rd!=null && rd.getStatus()!=null){					
						_status = rd.getStatus();
					}
				}
				if(!(_status==null)&&(_status.trim().compareTo("success")==0) ){			
					//密码验证成功，代码生成登录用户principals
	//				session.setAttribute(ConstSysParam.SILINK_PROPERTIES, getEncrptProperties(_status+","+username+","+password));
					
	//				session.setAttribute(ConstSysParam.SILINK_PROPERTIES, (_status+","+username+","+password));
					
					
	//				System.out.println("getSessionMsg:"+ getSilinkProperties(session));
	//				log.debug("getSessionMsg:"+ session.getAttribute(ConstSysParam.SILINK_PROPERTIES));
					
					PrincipalCollection ssoPrincipal = new SimplePrincipalCollection(
							userid, "ShiroRealm");
					WebSubject.Builder builder = new WebSubject.Builder(request,response);
					builder.principals(ssoPrincipal);
					builder.authenticated(true);
					WebSubject subject = builder.buildWebSubject();
					ThreadContext.bind(subject);
					ssoCheckin = true;
				}
			}
		}else{
		
			//正常登录系统
			if((!ssoCheckin)||(!useSSOLoginCheck)){
				so.setUserid(username);
		        try {
		        	Subject subject = SecurityUtils.getSubject();
		        	subject.login(token);
		        } catch (AuthenticationException e) {
		            log.error( "error.login.generic, Invalid username or password.  Please try again." );
//		            throw new UserameOrPasswordWrongException();
		        }
			}
		}
        
			
		Users usr = this.getCurrentUser();
		Department dept = null;
		
		//登录用户信息判断
		if((usr!=null) && (usr.getDeptid()!=null)){
//			Department dept = departmentService.getOne(usr.getDeptid());
			dept = queryDeptService.getOne(usr.getDeptid());
			usr.setDeptid(dept.getId());
			Map<String,String> jobmap = new HashMap<String,String>();
			jobmap.put("userid", usr.getId().toString());
			usr.setJobrole(queryJobroleService.getList(jobmap,false));
			SysConfig.setUsr(usr);
			
			session.setAttribute(ConstSysParam.SYS_USERID, usr.getIdentify());
		}else{       
	        so.setRetStatus("error");
	        return so;
		}
		
		
        //获取session
		if(session!=null){
			
			if((site!=null)&&(site.trim().length()>0)){
				//指定site值
				_site = site.trim();
			}else{
				//未指定site
				
				_site = dept.getSiteName()==null?default_site:dept.getSiteName();
				if((_site!=null)&&(_site.trim().length()>0)){
					_site = _site.trim();
				}
					
				
			}
			session.setAttribute(ConstSysParam.SITE_SESSION, _site);	
		}
			
        
        
        so.setRetStr(_site + mainPage);
        so.setRetData(usr);
        so.setRetStatus("success");
        return so;

	}	
	
	
	/**
	 * 
	 * @return 生成的password salt 值
	 */
	@RequestMapping("/biz/generateSalt.action")
	@ResponseBody
	public String generateSalt(){
		return new SecureRandomNumberGenerator().nextBytes().toHex();
	}
	
	/**
	 * 获取silink session 值
	 * @param session
	 * @return
	 */
	public String getDecrptProperties(String properties){
		
		EncrptUtil eu = new EncrptUtil();
		
		byte[] oStr=properties.getBytes();
		System.out.println("before decrpt msg:" + oStr);
		byte[] decrptMsg = eu.decryptor(oStr);
		
		String retStr= null;
		
		if(decrptMsg!=null){
			retStr = new String (decrptMsg);
			System.out.println("after decrpt msg:" + retStr);
			return retStr;
		}else
			return null;
//		System.out.println("session variables decrypted:" + new String(eu.decryptor((byte[])oStr)) );
	}
	
	public byte[] getEncrptProperties(String properties){
//		EncrpUtil eu = new EncrpUtil();
//		
//		System.out.println("before encrpt msg:" + properties);
//		
//		
//		byte[] encrptMsg = eu.encrytor(properties);
//		System.out.println("after encrpt msg:" + encrptMsg);
//		byte[] decrptMsg = eu.decryptor(encrptMsg);
//		System.out.println("after decrpt msg:" + new String (decrptMsg));
//		
//		return eu.encrytor(properties.toString());
		
		return properties.getBytes();
		
	}
	
	/**
	 * 
	 * @param username 用户名称
	 * @param password 用户密码
	 * @param uid	          用户编号
	 * @param salt		密码盐值
	 * @return	盐值为username+uid+salt ,sha256Hash方法，加密的password值
	 */
	@RequestMapping("/biz/generatePassword.action")
	@ResponseBody
	public Object generatePassword(@RequestParam(value="loginname",required=false) String username,
			@RequestParam(value="password",required=false) String password,
			@RequestParam(value="uid",required=false) String uid,@RequestParam(value="salt",required=false) String salt){
		
		String _salt = new SecureRandomNumberGenerator().nextBytes().toHex();
		//_salt = "50e314d581d4a4a88233c1700ec64691";
		
		return new SimpleHash(Sha256Hash.ALGORITHM_NAME,password,ByteSource.Util.bytes(username+uid+_salt),1);
		
		//return new Sha256Hash(password,ByteSource.Util.bytes(username+uid+salt)).toHex();
	}
	
	/**
	 * 获取当前站点首页
	 * @param session
	 * @return
	 */
	@RequestMapping(value="/main.action")
	public ModelAndView home(@RequestParam(value="site",required=false) String site,HttpSession session){
		
		if(session!=null){
			if(site!=null){
				default_site = site.trim();
				session.setAttribute(ConstSysParam.SITE_SESSION, default_site);	
			}else{
				Object _site = session.getAttribute(ConstSysParam.SITE_SESSION);
				if((_site!=null) && (_site.toString().trim().length()>0)){
					default_site = _site.toString().trim();
				}
			}
//		String orgcode= SysConfig.getConfig("orgcode");
//		if(orgcode!=null){
//			String sitepath = String.format("/site/%1$s/%2$s/home", orgcode,default_site);
//			return new ModelAndView(sitepath);
//		}else{		
//			return new ModelAndView("/site/" +default_site+ "/home");
//		}
		}
		
		return new ModelAndView("/site/" +default_site+ "/home");
	}
	
	/**
	 * 获取站点首页
	 * @param site	站点名称
	 * @return
	 */
	@RequestMapping(value="/{site}/main.action")
	public ModelAndView siteHome(@PathVariable("site") String site){		
		site = site==null?"risk":site;
		return new ModelAndView("/site/" +site+ "/home");
	}
	
	/**
	 * 获取站点动态指定页面
	 * @param site	站点名称
	 * @param code	页面代码
	 * @return
	 */
	@RequestMapping(value="/getPage.action")
	public ModelAndView getSitePage(HttpSession session,
			@RequestParam(value="code",required=false) String code){		
		if(session!=null){
			Object _site = session.getAttribute(ConstSysParam.SITE_SESSION);
			if((_site!=null) && (_site.toString().trim().length()>0)){
				default_site = _site.toString().trim();
			}
		}
		code = code==null?"home":code;
		String sitePath = String.format("/site/%1$s/%2$s", default_site,code);
		return new ModelAndView(sitePath);
	}
	
	/**
	 * 获取当前用户
	 * @return
	 */
	@RequestMapping(value="/biz/getCurentUser.action")
	public Users getCurrentUser() {
		// TODO Auto-generated method stub
//		Object currentUserIdentify =  SecurityUtils.getSubject().getPrincipal();		
		Subject subject = SecurityUtils.getSubject();
		Object currentUserIdentify =subject.getPrincipal();
        if( currentUserIdentify != null ) {
        	String uid = currentUserIdentify.toString();
        	Users usr = SysConfig.getUsr(uid);
        	if(usr==null){
        		usr = queryUserService.getOne(LongUtil.getLongValue(currentUserIdentify.toString(),null));
        	}
        	return usr;
        } else {
            return null;
        }        
	}
	
	/**
	 * 获取当前登录用户id
	 * @return
	 */
	
	public Long getCurrentUserid() {
		// TODO Auto-generated method stub
		return LongUtil.getLongValue(SecurityUtils.getSubject().getPrincipal().toString(),null);
	}
	
	/**
	 * 获取当前登录用户唯一标识
	 * @return
	 */
	public String getCurrentUserIdentify(){
		Subject subject = SecurityUtils.getSubject();
		Object userIdentify = subject.getPrincipal();
		return userIdentify.toString();
	}
	
	/**
	 * 登出
	 * @param session
	 * @return
	 */
	@RequestMapping("/biz/logout.action")
	@ResponseBody
	public RetDomain sysLogout(HttpSession session){
		String _site = "";
		
		//获取session site
		Object siteObj = session.getAttribute(ConstSysParam.SITE_SESSION);
		if(siteObj!=null){
			String sessionSite = siteObj.toString().trim();
			if(sessionSite.length()>0){
				_site = sessionSite;
			}
		}
		SecurityUtils.getSubject().logout();
		RetDomain domain = new RetDomain();
		domain.setSuccessMsg(_site);
		return domain;
	}
	
	/**
	 * 
	 * @return 用户具备访问权限的业务模块清单
	 * @throws Exception 
	 */
	@RequestMapping("/biz/getPermissions.action")
	@ResponseBody
	public List<Permissions> getPermissions(HttpSession session) throws SessionExpiredException{
//		
//		if(!SysConfig.getUsingSSO())
//			return permissionService.getUserMenu();
//		else
			return queryPermissionService.getUserMenu(this.getCurrentUserIdentify(),session);
	}
	
	
	
	
}
